﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Web.Mvc;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using Sherwood.SignOn.Server;
using Sherwood.SignOn.Server.Models;
using Sherwood.SignOn.Server.Models.ViewModels;
using Sherwood.SignOn.Server.Controllers;
using Sherwood.SignOn.Server.Models.Repositories;
using Sherwood.SignOn.Server.Models.Services;

namespace Sherwood.SignOn.Server.Tests
{
    [TestClass]
    public class ChangePasswordTests : TestBase
    {
        /// <summary>
        /// Tests change of password.
        /// This should redirect to login page if no verification code is supplied.
        /// Verification code must match the verification code in the database.
        /// New passwords must match before password is changed.
        /// Verification status must change back to "verified" and password changed once password change has taken place.
        /// </summary>
        [TestMethod]
        public void ChangePasswordTest()
        {
            //Assemble

            IUserAccount user = TestHelper.RegisterValidDummyUser("NewUser", "rvanoord@allmail.net");
            //IUserAccount user = Data.UserAccounts.GetUserAccountByUsername("NewUser");
            UserAccountController accountController = new UserAccountController();
            ForgotPasswordViewModel forgotPasswordModel = new ForgotPasswordViewModel();
            forgotPasswordModel.UserName = "NewUser";
            accountController.ForgotPassword(forgotPasswordModel); //Send verification code
            user = Data.UserAccounts.GetUserAccountByUsername("NewUser"); //reload user
            string actualVerificationCode = user.VerificationCode;
            string originalPasswordHash = user.PasswordHash;

            //Act
            ChangePasswordViewModel viewModel = new ChangePasswordViewModel();
            accountController = new UserAccountController();
            RedirectResult noCodeResult = accountController.ChangePassword(viewModel) as RedirectResult;
            user = Data.UserAccounts.GetUserAccountByUsername("NewUser");//reload user
            string noCodePasswordHash = user.PasswordHash;

            viewModel.VerificationCode = "falseVerificationCode";
            viewModel.UserAccountId = user.Id.ToString();
            accountController = new UserAccountController();
            ViewResult badCodeResult = accountController.ChangePassword(viewModel) as ViewResult;
            user = Data.UserAccounts.GetUserAccountByUsername("NewUser");//reload user
            bool badCodeErrors = TestHelper.HasError(accountController.ModelState);
            string badCodePasswordHash = user.PasswordHash;

            viewModel.VerificationCode = actualVerificationCode;
            viewModel.NewPassword1 = "Password";
            viewModel.NewPassword2 = "AnotherPassword";
            accountController = new UserAccountController();
            ViewResult passwordMismatchResult = accountController.ChangePassword(viewModel) as ViewResult;
            bool passwordMismatchErrors = TestHelper.HasError(accountController.ModelState);
            user = Data.UserAccounts.GetUserAccountByUsername("NewUser");//reload user
            string passwordMismatchPasswordHash = user.PasswordHash;

            viewModel.NewPassword2 = "Password";
            accountController = new UserAccountController();
            ViewResult passResult = accountController.ChangePassword(viewModel) as ViewResult;
            bool passErrors = TestHelper.HasError(accountController.ModelState);
            user = Data.UserAccounts.GetUserAccountByUsername("NewUser");//reload user
            string passPasswordHash = user.PasswordHash;


            //Assert
            Assert.IsNotNull(noCodeResult);
            Assert.IsTrue(noCodeResult.Url.Contains("SignIn") || noCodeResult.Url.Equals("~/"));
            Assert.AreEqual<string>(noCodePasswordHash, originalPasswordHash);

            Assert.IsNotNull(badCodeResult);
            Assert.IsTrue(badCodeErrors);
            Assert.AreEqual<string>(badCodePasswordHash, originalPasswordHash);

            Assert.IsNotNull(passwordMismatchResult);
            Assert.IsTrue(passwordMismatchErrors);
            Assert.AreEqual<string>(passwordMismatchPasswordHash, originalPasswordHash);


            Assert.IsNotNull(passResult);
            Assert.IsFalse(passErrors);
            Assert.IsTrue(user.VerificationStatus == VerificationStatus.Verified);
            Assert.AreNotEqual<string>(passPasswordHash, originalPasswordHash);

        }

    }
}
